package cc.minos.components.textflow
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.engine.BreakOpportunity;
	import flash.text.engine.FontPosture;
	import flash.text.engine.FontWeight;
	import flashx.textLayout.edit.EditManager;
	import flashx.textLayout.edit.ISelectionManager;
	import flashx.textLayout.edit.SelectionManager;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.events.CompositionCompleteEvent;
	import flashx.textLayout.events.FlowElementMouseEvent;
	import flashx.textLayout.events.StatusChangeEvent;
	import flashx.textLayout.events.TextLayoutEvent;
	import flashx.textLayout.events.UpdateCompleteEvent;
	import flashx.textLayout.formats.TextDecoration;
	import flashx.textLayout.formats.TextLayoutFormat;
	
	/**
	 * ...
	 * @author Minos
	 */
	public class TextLayout extends Component implements IFontStyle , IScrollAbleV
	{
		public static const INPUT:String = "input";
		public static const DYNAMIC:String = "dynamic";
		
		protected var canvas:Sprite;
		protected var scrollV:IScrollBar;
		protected var scrollH:IScrollBar;
		
		protected var controller:CustomController;
		protected var config:CustomConfiguration;
		protected var composer:CustomComposer;
		protected var manager:ISelectionManager;
		protected var flow:TextFlow;
		
		protected var padding:Number = 3;
		
		public function TextLayout( w:Number = 100 , h:Number = 100 , type:String = TextLayout.DYNAMIC )
		{
			super();
			this._type = type;
			//
			var format:TextLayoutFormat = new TextLayoutFormat();
			format.fontFamily = "微软雅黑,宋体,黑体,Arial";
			format.fontSize = 12;
			format.color = '0x000000';
			format.fontWeight = FontWeight.NORMAL;
			format.fontStyle = FontPosture.NORMAL;
			format.textDecoration = TextDecoration.NONE;
			format.lineHeight = '120%';
			format.breakOpportunity = BreakOpportunity.NONE;
			format.linkNormalFormat = { textDecoration: TextDecoration.UNDERLINE };
			format.linkHoverFormat = { textDecoration: TextDecoration.NONE };
			
			addChild( canvas = new Sprite );
			controller = new CustomController( canvas , w , h );
			config = new CustomConfiguration();
			config.textFlowInitialFormat = format;
			composer = new CustomComposer();
			composer.addController( controller );
			
			if ( !manager )
			{
				if ( type == TextLayout.INPUT )
					manager = new EditManager();
				else
					manager = new SelectionManager();
			}
			
			flow = new TextFlow( config );
			flow.flowComposer = composer;
			flow.interactionManager = manager;
			flow.addEventListener( StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE , onGraphicStatusChangeEvent );
			flow.addEventListener( CompositionCompleteEvent.COMPOSITION_COMPLETE , onComposeListener );
			flow.addEventListener( TextLayoutEvent.SCROLL , onScroll );
			flow.addEventListener( UpdateCompleteEvent.UPDATE_COMPLETE , onUpdateComplete );
			flow.addEventListener( FlowElementMouseEvent.CLICK , onLink );
			
			setSize( w , h );
		}
		
		/**
		 * 刷新textflow的控制器controller
		 */
		protected function updateFlow():void
		{
			composer.updateAllControllers();
		}
		
		/**
		 * 更新滚动条
		 */
		protected function updateScrollBar():void
		{
			if ( scrollV )
				scrollV.update();
			if ( scrollH )
				scrollH.update();
		}
		
		override public function setSize( w:Object , h:Object ):void
		{
			
			var skin:DisplayObject = scrollV ? scrollV.getScrollBar() : null;
			var controllerWidth:Number = skin ? ( w - skin.width ) : w;
			var controllerHeight:Number = h;
			controller.setCompositionSize( controllerWidth , controllerHeight );
			if ( skin )
				skin.x = w - skin.width;
			update();
			
			super.setSize( w , h );
		}
		
		/**
		 * 刷新
		 * textflow改变后必须刷新controller
		 */
		public function update():void
		{
			updateFlow();
			updateScrollBar();
			dispatchEvent( new Event( Event.CHANGE ) );
		}
		
		/**
		 * 设置焦点
		 */
		public function setFocus():void
		{
			manager.setFocus();
		}
		
		/**
		 * 清除文本
		 */
		public function clearText():void
		{
			while ( flow.numChildren > 0 )
			{
				flow.removeChildAt( 0 );
			}
			update();
		}
		
		public function setScrollBarV( sc:IScrollBar ):void
		{
			//
			scrollV = sc;
			if ( scrollV )
			{
				scrollV.target = this;
				
				var skin:DisplayObject = addChild( scrollV.getScrollBar() );
				skin.x = _width - skin.width;
				controller.setCompositionSize( _width - skin.width , _height );
				//onScroll( null );
				update();
			}
		}
		
		public function setScrollBarH( sc:IScrollAbleH ):void
		{
			
		}
		
		/* INTERFACE cc.minos.components.IFontStyle */
		
		public function get fontFamily():*
		{
			return flow.fontFamily;
		}
		
		public function set fontFamily( value:* ):void
		{
			flow.fontFamily = value;
		}
		
		public function get fontSize():*
		{
			return flow.fontSize;
		}
		
		public function set fontSize( value:* ):void
		{
			flow.fontSize = value;
		}
		
		public function get color():*
		{
			return flow.color;
		}
		
		public function set color( value:* ):void
		{
			flow.color = value;
		}
		
		public function get fontWeight():*
		{
			return flow.fontWeight;
		}
		
		public function set fontWeight( value:* ):void
		{
			flow.fontWeight = value;
		}
		
		public function get fontStyle():*
		{
			return flow.fontStyle;
		}
		
		public function set fontStyle( value:* ):void
		{
			flow.fontStyle = value;
		}
		
		public function get textDecoration():*
		{
			return flow.textDecoration;
		}
		
		public function set textDecoration( value:* ):void
		{
			flow.textDecoration = value;
		}
		
		/* INTERFACE cc.minos.components.IScrollAbleH
		
		   private const MIN_SCROLL_H:int = 1;
		
		   public function get scrollH():Number
		   {
		   return controller.horizontalScrollPosition;
		   }
		
		   public function set scrollH( value:Number ):void
		   {
		   //_scrollH = value;
		   var temp:Number = scrollH;
		   if ( value < MIN_SCROLL_H )
		   value = MIN_SCROLL_H;
		   else if ( value > maxScrollH )
		   value = maxScrollH;
		
		   controller.horizontalScrollPosition = value + MIN_SCROLL_H;
		
		   if ( value != temp )
		   dispatchEvent( new Event( Event.SCROLL ) );
		   }
		
		   public function get maxScrollH():Number
		   {
		   var val:Number;
		   val = MIN_SCROLL_H + 1 + contentWidth - controller.compositionWidth;
		   return val < 1 ? 1 : val;
		   }
		
		   public function get contentWidth():Number
		   {
		   return controller["contentWidth"];
		   }
		
		 */
		
		/* INTERFACE cc.minos.components.IScrollAbleV */
		
		private const MIN_SCROLL_V:int = 1;
		
		public function get scrollV():Number
		{
			return controller.verticalScrollPosition;
		}
		
		public function set scrollV( value:Number ):void
		{
			var temp:Number = scrollV;
			if ( value < MIN_SCROLL_V )
				value = MIN_SCROLL_V;
			else if ( value > maxScrollV )
				value = maxScrollV;
			
			controller.verticalScrollPosition = value + MIN_SCROLL_V;
			
			if ( value != temp )
				dispatchEvent( new Event( Event.SCROLL ) );
		}
		
		public function get maxScrollV():Number
		{
			var val:Number;
			val = MIN_SCROLL_V + 1 + contentHeight - controller.compositionHeight;
			return val < 1 ? 1 : val;
		}
		
		public function get contentHeight():Number
		{
			return controller[ 'contentHeight' ];
		}
		
		// ===== 事件处理 ===== //
		
		private function onGraphicStatusChangeEvent( e:StatusChangeEvent ):void
		{
			update();
		}
		
		private function onComposeListener( e:CompositionCompleteEvent ):void
		{
			update();
		}
		
		private function onUpdateComplete( e:UpdateCompleteEvent ):void
		{
			updateScrollBar();
		}
		
		private function onLink( e:FlowElementMouseEvent ):void
		{
		}
		
		private function onScroll( e:TextLayoutEvent ):void
		{
			dispatchEvent( new Event( Event.SCROLL ) );
		}
	
	}

}